package com.diy.sigmund.diycommon.spring.advice;

import com.diy.sigmund.diycommon.entity.ResultMsg;
import java.util.Map;
import java.util.Objects;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.Order;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/**
 * 对方法出参添加traceId,依赖tlog
 *
 * @author ylm-sigmund
 * @since 2022/8/7 00:31
 */
@ControllerAdvice
@Order(8)
public class TraceIdResponseBodyAdvice implements ResponseBodyAdvice<Object> {

    private final static Logger log = LoggerFactory.getLogger(TraceIdResponseBodyAdvice.class);

    @Override
    public boolean supports(MethodParameter methodParameter, Class aClass) {
        // log.info("TraceIdResponseBodyAdvice supports");
        return true;
    }

    /**
     * <br>在选择HttpMessageConverter之后和调用它的 write 方法之前调用。
     * <br>参数：
     * <br>body – 要写入的正文
     * <br>returnType - 控制器方法的返回类型
     * <br>selectedContentType – 通过内容协商选择的内容类型
     * <br>selectedConverterType – 选择写入响应的转换器类型
     * <br>request – 当前请求
     * <br>response – 当前响应
     * <br>回报：
     * <br>传入的主体或修改的（可能是新的）实例
     */
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class aClass,
            ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        Map<String, String> context = MDC.getCopyOfContextMap();
        // {"tlogSpanId":"0","preIp":"NONE","tl":"[2972668999271400]","preIvkApp":"NONE","preIvkHost":"NONE","tlogTraceId":"2972668999271400","currIp":"192.168.223.1"}
        if (body instanceof ResultMsg && Objects.nonNull(context)) {
            ((ResultMsg) body).setTraceId(context.get("tlogTraceId"));
            log.info("对方法出参添加traceId:{}", methodParameter.getMethod().toString());
            log.info("响应类型响应类型{}",mediaType);
        }
        return body;
    }
}
